<?php

  /**
   * UserController
   *
   * Класс контроллера для работы с учетными записями
   */

  final class UserController extends XMLController
  {
  // имя папки, где размещены аватары
    const AVATARS = "avatars";

    /**
     * предопределенные действия
     *
     * @return array
     * @access public
     */
    public function actions()
    {
      return array(
        "reg"     => "AjaxAction",
        "recall"  => "RenderAction",
        "profile" => "AjaxAction"
      ) + parent::actions();
    }

    /**
     * Action авторизация пользователя
     *
     * $_POST == array(
     *   "user" => array(
     *     "login" => "логин",
     *     "paswd" => "пароль"
     *   ),
     *   "scenario" => "сценарий входа"
     * )
     *
     * @return void
     * @access public
     */
    public function actionLogin()
    {
      $model = new Login($this->getParam("user"), $this->getParam("scenario", "login"));
      /** @var $app WebApplication */
      $app = $this->app;

      WebApplication::response($model->validate()
                                 ? ($app->user->isGuest
                                      ? array("id" => User::model()->findByAttributes(array("login" => $model->login))->id)
                                      : array("href" => $app->session["current"]))
                                 : array("errors" => array("login" => $model->getError("login"), "paswd" => $model->getError("paswd"))));
    }

    /**
     * Acvtion завершение сеанса
     *
     * @return void
     * @access public
     */
    public function actionLogout()
    {
      /** @var $app WebApplication */
      $app = $this->app;
      $app->user->logout(false);
      WebApplication::response(array("href" => $app->session["current"]));
    }

    /**
     * Action регистрация нового пользователя
     *
     * $_GET  == array("acode" => "код активации")
     * $_POST == array(
     *   "User" => array(
     *     "photo_type" => "тип изображения(фото или аватар)",
     *     "photo"      => "название файла-изображения",
     *     "name"       => "имя",
     *     "login"      => "логин",
     *     "paswd"      => "пароль",
     *     "confirm"    => "подтверждение пароля",
     *     "email"      => "электропочта"
     *   )
     * )
     *
     * @return void
     * @access public
     */
    public function actionReg()
    {
      /** @var $app WebApplication */
      $app = $this->app;
      /** @var $user User */

      if (($acode = $app->getParam("acode")) !== null) // активация профиля
      {
        $user     = User::model()->findByPk(mb_substr($acode, 32));
        $userCode = $user ? $user->activate_code : "";
        $activate = $user && (($userCode === null) || ($userCode == mb_substr($acode, 0, 32)));

        if ($activate)
        {
          if ($userCode)
            $user->saveAttributes(array("activate_code" => null));

          $identity = new UserIdentity($user->login, $user->paswd);
          $identity->setUser($user);
          $app->user->login($identity);
        }

        if ($app->isAjaxRequest)
          self::responseBool($activate);
        else
          $this->runPreAction(array(
            "view" => "message",
            "data" => $activate ? array("message" => "Активация выполнена") : array("message" => "Активация не выполнена", "class" => array("errorMessage"))
          ));
      }
      else
      {
        $user = new User();
        $data = $this->getParam("User");

        if (is_array($data)) // регистрация
        {
          $user->attributes = $data;

          if ($user->validate())
          {
            if ($user->save(false))
              if ($data["vkontakte"])
              {
                $user->saveAttributes(array("activate_code" => null));
                $msg = array("message" => "Регистрация прошла успешно. Войдите на сайт под своим логином");
              }
              else
                if ($this->sendmail("Подтверждение регистрации", $user, "mail", array("paswd" => $data["paswd"])))
                  $msg = array("message" => "Для завершения регистрации Вам выслано письмо, содержащее код активации");
                else
                  $user->delete();
            if (!isset($msg))
              $msg = array(
                "message" => "Регистрация завершилась неудачей. Попробуйте повторить попытку позднее",
                "class"   => array("errorMessage")
              );

            $this->runPreAction(array("view" => "message", "data" => $msg));
            return;
          }
        }

      // форма регистрации
        $data = array("form" => $this->viewOutput(array(
          "title"  => "Регистрация нового пользователя",
          "model"  => $user,
          "submit" => "Зарегистрироваться"
        ), "form"));
        if ($app->getParam("iframe"))
          WebApplication::response($this->viewOutput($data, $this->id), "text/html");
        else
          $this->runPreAction(array("data" => $data));
      }
    }

    /**
     * Action восстановление пароля
     *
     * $_GET  == array("paswd" => "старый пароль")
     * $_POST == array("login" => "логин")
     *
     * @return void
     * @access public
     */
    public function actionRecall()
    {
      /** @var $user User */

      if (($paswd = $this->app->getParam("paswd")) !== null) // задание нового пароля
      {
        $user = User::model()->findByPk(mb_substr($paswd, 32));

        if ($user && ($user->paswd == mb_substr($paswd, 0, 32)))
        {
          // TODO сменить пароль
        }
        else
          $this->currentRedirect();
      }
      else // запрос на восстановление пароля
      {
        if ($user = User::model()->findByAttributes(array("login" => $this->getParam("login"))))
          WebApplication::validate($this->sendmail("Восстановление пароля", $user, $this->action->id), 500, "Не удалось отправить письмо");

        self::responseBool($user !== null);
      }
    }

    /**
     * Action отобразить профиль пользователя
     *
     * @param int $id идентификатор пользователя
     * @return void
     * @access public
     */
    public function actionProfile($id)
    {
      /** @var $user User */
      $user = User::model();
      $user = is_numeric($id) ? $user->findByPk($id) : $user->findByAttributes(array("login" => $id));
      WebApplication::validate($user);
      $this->runPreAction(array("data" => array("user" => $user)));
    }

    /**
     * Action обновить профиль пользователя
     *
     * $_POST == array(
     *   "field" => "имя поля для изменения",
     *   "value" => "новое значение"
     *   "type"  => опционально
     * )
     *
     * @return void
     * @access public
     */
    public function actionUpdate()
    {
      $this->checkAccess("edit_profile");

      /** @var $user User */
      $user  = $this->app->authUser;
      $field = $this->getParam("field");
      WebApplication::validate($user->hasAttribute($field));

      $oldValue     = $user->$field;
      $user->$field = $value = $this->getParam("value");
      if ($user->validate(array($field)))
        if (strcasecmp($field, "photo"))
        {
          $url      = $user->getAccountUrl($field);
          $response = array("html" => $url ? CHtml::link($value, $url) : $value);
        }
        else
        {
          $oldType          = $user->photo_type;
          $user->photo_type = $type = $this->getParam("type");
          WebApplication::validate($user->validate(array("photo_type")));
          $user->$field     = $oldValue;
          $user->photo_type = $oldType;
          $user->removePhoto();
          if ($user->saveAttributes(array($field => basename($value), "photo_type" => $type)))
            $response = array("src" => $user->getAvatar());
        }
      else
        $response = array("msg" => $user->getError($field));

      if (isset($response["html"]))
        $user->saveAttributes(array($field => $value));

      WebApplication::response($response);
    }

    /**
     * Action проверить доступность логина
     *
     * @param array $User пользовательская информация
     * @return void
     * @access public
     */
    public function actionCheckLogin(array $User)
    {
      self::responseBool(!User::model()->exists("`login`='$User[login]'"));
    }

    /**
     * Action сменить пароль
     *
     * $_POST == array(
     *   "user" => array(
     *     "id"       => идентификатор пользователя,
     *     "paswd"    => "старый пароль",
     *     "newpaswd" => "новый пароль",
     *     "confirm"  => "подтверждение пароля",
     *   )
     * )
     *
     * @return void
     * @access public
     */
    public function actionChPaswd()
    {
      // TODO сменить пароль
      WebApplication::validate(false, 500);
    }

    /**
     * Action отобразить доступные аватары
     *
     * @return void
     * @access public
     */
    public function actionAvatars()
    {
      $avatars = array_filter(
        glob(WebApplication::createPath(array($this->app->contentPath, ContentController::IMG_FULL, self::AVATARS, "*.*"))),
        create_function('$a', 'return is_file($a);')
      );
      $avatars = array_map(create_function(
        '$a',
        'return Yii::app()->contentUrl."/".ContentController::IMG_FULL."/".UserController::AVATARS."/".basename($a);'
      ), $avatars);

      WebApplication::response($avatars);
    }

    /**
     * отправить письмо
     *
     * @param string $subject тема письма
     * @param User   $user    экземпляр модели пользователя, которому отправляется письмо
     * @param string $view    имя представления
     * @param array  $data    данные для рендеринга
     * @return bool
     * @access private
     */
    private function sendmail($subject, User $user, $view, array $data = array())
    {
      return Swift_Mailer::newInstance(Swift_MailTransport::newInstance())->send(
        Swift_Message::newInstance(
          $subject = "$subject на сайте $_SERVER[SERVER_NAME]",
          $this->viewOutput(array("title" => $subject, "user" => $user) + $data, $view),
          "text/html",
          "utf-8"
        )->setFrom("no-reply@$_SERVER[SERVER_NAME]")->setTo($user->email)
      );
    }
  }

?>
